#include "LTC2990.h"



LTC2990_Device ltc_dev1 = {0};
LTC2990_Device ltc_dev2 = {0};

static HAL_StatusTypeDef LTC2990_WriteReg(LTC2990_Device *dev, uint8_t reg, uint8_t data);
static HAL_StatusTypeDef LTC2990_ReadReg(LTC2990_Device *dev, uint8_t reg, uint8_t *data);
static HAL_StatusTypeDef LTC2990_Trigger(LTC2990_Device *dev);
static HAL_StatusTypeDef LTC2990_WaitReady(LTC2990_Device *dev, uint32_t timeout);
static HAL_StatusTypeDef LTC2990_ReadInternalTemp(LTC2990_Device *dev, float *temp);
static HAL_StatusTypeDef LTC2990_ReadRemote1Temp(LTC2990_Device *dev, float *temp, float ideality);
static HAL_StatusTypeDef LTC2990_ReadRemote2Temp(LTC2990_Device *dev, float *temp, float ideality);


HAL_StatusTypeDef LTC2990_Init(LTC2990_Device *p_dev, I2C_HandleTypeDef *p_hi2c, uint8_t addr, LTC2990_TempUnit unit, LTC2990_IsRepeat repeat, uint8_t mode)
{


    p_dev->hi2c = p_hi2c;
    p_dev->addr = addr;
    p_dev->unit = unit;
    p_dev->repeat = repeat;
    p_dev->mode = mode;

    static uint8_t control_reg = 0;
    control_reg |= (unit << LTC2990_CTRL_TEMP_FORMAT_BIT);   
    control_reg |= (repeat << LTC2990_CTRL_REPEAT_MODE_BIT); 
    control_reg |= mode;                                     

    return LTC2990_WriteReg(p_dev, LTC2990_REG_CONTROL, control_reg);
}

static HAL_StatusTypeDef LTC2990_WriteReg(LTC2990_Device *p_dev, uint8_t reg, uint8_t data)
{
    return HAL_I2C_Mem_Write(
        p_dev->hi2c, 
        p_dev->addr,
        reg,                  
        I2C_MEMADD_SIZE_8BIT,
        &data,               
        1,                   
        100                   
    );
}

static HAL_StatusTypeDef LTC2990_ReadReg(LTC2990_Device *p_dev, uint8_t reg, uint8_t *p_data)
{
    return HAL_I2C_Mem_Read(
        p_dev->hi2c,
        p_dev->addr,
        reg,
        I2C_MEMADD_SIZE_8BIT,
        p_data,
        1,
        100);
}


static HAL_StatusTypeDef LTC2990_Trigger(LTC2990_Device *p_dev)
{
    uint8_t trig_data = 0x01; 
    return LTC2990_WriteReg(p_dev, LTC2990_REG_TRIGGER, trig_data);
}

static HAL_StatusTypeDef LTC2990_WaitReady(LTC2990_Device *p_dev, uint32_t timeout)
{
    uint8_t status = 0;

    while (timeout--)
    {
        if (LTC2990_ReadReg(p_dev, LTC2990_REG_STATUS, &status) != HAL_OK)
        {
            return HAL_ERROR;
        }

        if ((status & LTC2990_STATUS_BUSY_MASK) == 0)
        {
            return HAL_OK;
        }
        HAL_Delay(1); 
    }
    return HAL_TIMEOUT; 
}


static float data2Temp(uint8_t msb, uint8_t lsb)
{
  int16_t diff_T = 0;
  diff_T = (msb << 8) | lsb;

  if (diff_T & (1 << 12))
  {
    diff_T = -4096 + (diff_T & (0x0FFF));
  }
  else
  {
    diff_T = diff_T & (0x0FFF);
  }

  float Temp = 0;
  Temp = (float)diff_T * 0.0625f;

  return Temp;
}

#if 0

static float data2Vol(uint8_t msb, uint8_t lsb)
{
  int16_t diff_V = 0;
  diff_V = (msb << 8) | lsb;

  if (diff_V & (1 << 14))
  {
    diff_V = -16384 + (diff_V & (0x03FFF));
  }
  else
  {
    diff_V = diff_V & (0x3FFF);
  }

  float Vol = 0;
  Vol = (float)diff_V * 19.42;

  return Vol;
}
#endif


static HAL_StatusTypeDef LTC2990_ReadInternalTemp(LTC2990_Device *p_dev, float *p_temp)
{
    uint8_t msb, lsb;
    if (LTC2990_ReadReg(p_dev, LTC2990_REG_TINT_MSB, &msb) != HAL_OK)
    {
        return HAL_ERROR;
    }

    if (LTC2990_ReadReg(p_dev, LTC2990_REG_TINT_LSB, &lsb) != HAL_OK)
    {
        return HAL_ERROR;
    }

    int16_t raw = ((msb & 0x1F) << 8) | lsb;
    float temp_celsius = raw * 0.0625f;      

    if (p_dev->unit == LTC2990_TEMP_KELVIN)
    {
        *p_temp = temp_celsius + 273.15f;
    }
    else
    {
        *p_temp = temp_celsius;
    }
    return HAL_OK;
}


 
static HAL_StatusTypeDef LTC2990_ReadRemote1Temp(LTC2990_Device *p_dev, float *p_temp, float ideality)
{
   uint8_t msb, lsb;
   float temp_celsius;

    if (LTC2990_ReadReg(p_dev, LTC2990_REG_TREMOTE1_MSB, &msb) != HAL_OK)
        return HAL_ERROR;
    if (LTC2990_ReadReg(p_dev, LTC2990_REG_TREMOTE1_LSB, &lsb) != HAL_OK)
        return HAL_ERROR;

    temp_celsius = data2Temp(msb, lsb);

    if (ideality != 1.004f)
    {
        temp_celsius = (1.004f / ideality) * temp_celsius;
    }

    if (p_dev->unit == LTC2990_TEMP_KELVIN)
    {
        *p_temp = temp_celsius + 273.15f;
    }
    else
    {
        *p_temp = temp_celsius;
    }
    return HAL_OK;
}

static HAL_StatusTypeDef LTC2990_ReadRemote2Temp(LTC2990_Device *dev, float *temp, float ideality)
{
    uint8_t msb, lsb;
    float temp_celsius;
    if (LTC2990_ReadReg(dev, LTC2990_REG_TREMOTE2_MSB, &msb) != HAL_OK)
        return HAL_ERROR;
    if (LTC2990_ReadReg(dev, LTC2990_REG_TREMOTE2_LSB, &lsb) != HAL_OK)
        return HAL_ERROR;

    temp_celsius = data2Temp(msb, lsb);


    if (ideality != 1.004f)
    {
        temp_celsius = (1.004f / ideality) * temp_celsius;
    }

    if (dev->unit == LTC2990_TEMP_KELVIN)
    {
        *temp = temp_celsius + 273.15f;
    }
    else
    {
        *temp = temp_celsius;
    }

    return HAL_OK;
}


HAL_StatusTypeDef LTC2990_MeasureInternal(LTC2990_Device *p_dev, float *p_temp)
{
    if (!p_dev->repeat)
    {
   
        if (LTC2990_Trigger(p_dev) != HAL_OK)
        {
            return HAL_ERROR;
        }

        if (LTC2990_WaitReady(p_dev, 100) != HAL_OK)
            return HAL_ERROR; 
    }

    return LTC2990_ReadInternalTemp(p_dev, p_temp);
}


HAL_StatusTypeDef LTC2990_MeasureRemote1(LTC2990_Device *p_dev, float *p_temp, float ideality)
{
    if (!p_dev->repeat)
    {
      
        if (LTC2990_Trigger(p_dev) != HAL_OK)
        {
            return HAL_ERROR;
        }

        if (LTC2990_WaitReady(p_dev, 100) != HAL_OK)
            return HAL_ERROR; // ��ʱ100ms
    }

    return LTC2990_ReadRemote1Temp(p_dev, p_temp, ideality);
}

HAL_StatusTypeDef LTC2990_MeasureRemote2(LTC2990_Device *p_dev, float *p_temp, float ideality)
{
    if (!p_dev->repeat)
    {
        
        if (LTC2990_Trigger(p_dev) != HAL_OK)
        {
            return HAL_ERROR;
        }

        if (LTC2990_WaitReady(p_dev, 100) != HAL_OK)
            return HAL_ERROR;
    }

    return LTC2990_ReadRemote2Temp(p_dev, p_temp, ideality);
}
